import { Disposable, InjectionToken, container } from "tsyringe";
import { ISender } from "../core/sender";
import { getSender } from "../tokens/core";
import { getCloudHost, getCloudPort, getDeviceUuid } from "../tokens/const";
import { WS_CONNECT, WS_CONNECT_CLOSE } from "../tokens";
import { parseJson } from "../utils";
import { Timer } from "./timer";
declare const web: any;
export class WS implements Disposable {
    isClosed: boolean = true;
    pongTime: Date = new Date();
    url: string;
    socket: any;
    private emitter: ISender;
    private isExit: boolean;
    private timer: Timer;
    connect() {
        try {
            this.emitter = getSender()
            const uuid = getDeviceUuid()
            const host = getCloudHost()
            const port = getCloudPort()
            this.timer = container.resolve(Timer)
            const url = `ws://${host}:${port}/autojs/core/autox/ws?uuid=${uuid}`;
            const ws = web.newWebSocket(url);
            // 监听他的各种事件
            ws.on("open", (res, ws) => {
                toastLog(`连接服务器成功 ${url}`)
                this.socket = ws;
                this.emitter.send(WS_CONNECT, new Date().getTime())
            }).on("failure", (err, res, ws) => {
                toastLog(`连接服务器失败`)
                if (this.isExit) {
                    return;
                }
                sleep(1000 * 3)
                this.connect();
            }).on("closing", (code, reason, ws) => {
                this.emitter.send(WS_CONNECT_CLOSE, new Date().getTime())
            }).on("text", (text: string, ws) => {
                const data = parseJson(text)
                const { type, payload } = data;
                console.log(`send ${type} to server`)
                if (type === 'pong') {
                    return;
                }
                if (type === 'ping') {
                    this.send('pong', new Date().getTime())
                    return;
                }
                this.emitter.send(type, payload)
            }).on("binary", (bytes, ws) => {
                console.info("收到二进制消息:");
                console.info("hex: ", bytes.hex());
                console.info("base64: ", bytes.base64());
                console.info("md5: ", bytes.md5());
                console.info("size: ", bytes.size());
                console.info("bytes: ", bytes.toByteArray());
            }).on("closed", (code, reason, ws) => {
                if (this.isExit) {
                    return;
                }
                toastLog(`断开连接， 正在尝试重连`)
                this.connect()
            });
        } catch (e) {
            sleep(3000)
            this.connect();
        }
    }
    destory() {
        try {
            if (this.socket) {
                this.socket.cancel()
                this.socket.close(1000, null)
            }
            this.socket = null;
        } catch (e) {
            toastLog(`销毁Websocket失败${e.message}`)
        }
    }
    send<T>(type: InjectionToken<T>, payload: T) {
        try {
            console.log(`send ${type as string} to server`);
            const data = JSON.stringify({
                type: type,
                payload
            });
            this.socket.send(data);
        } catch (e) {
            toastLog(e.message);
            this.connect();
        }
    }
    dispose(): void | Promise<void> {
        this.isExit = true;
        this.destory()
    }
}
